<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Component;

use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveArg;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\Metadata\UrlMapping;
use Symfony\UX\LiveComponent\Tests\Fixtures\Dto\Address;

#[AsLiveComponent('component_with_url_bound_props')]
class ComponentWithUrlBoundProps
{
    use DefaultActionTrait;

    #[LiveProp(url: true)]
    public ?string $stringProp = null;

    #[LiveProp(url: true)]
    public ?int $intProp = null;

    #[LiveProp(url: true)]
    public array $arrayProp = [];

    #[LiveProp(url: new UrlMapping(as: 'arr_alias'))]
    public array $arrayPropAlias = [];

    #[LiveProp(writable: true, fieldName: 'getArrayFieldName()', url: true)]
    public array $arrayPropFieldName = [];

    #[LiveProp]
    public ?string $unboundProp = null;

    #[LiveProp(url: true)]
    public ?Address $objectProp = null;

    #[LiveProp(url: true, useSerializerForHydration: true)]
    public ?Address $objectPropWithSerializerForHydration = null;

    #[LiveProp(fieldName: 'field1', url: true)]
    public ?string $propWithField1 = null;

    #[LiveProp(fieldName: 'getField2()', url: true)]
    public ?string $propWithField2 = null;

    #[LiveProp(modifier: 'modifyMaybeBoundProp')]
    public ?string $maybeBoundProp = null;

    #[LiveProp]
    public ?bool $maybeBoundPropInUrl = false;

    #[LiveProp(url: new UrlMapping(as: 'p'), modifier: 'modifyPropertyWithModifierAndAlias')]
    public ?string $propertyWithModifierAndAlias = null;

    public function modifyPropertyWithModifierAndAlias(LiveProp $liveProp): LiveProp
    {
        $urlMapping = $liveProp->url();
        if (!$urlMapping instanceof UrlMapping) {
            return $liveProp;
        }

        return $liveProp->withUrl(new UrlMapping(as: 'alias_' . $urlMapping->as));
    }

    public function getField2(): string
    {
        return 'field2';
    }

    public function modifyMaybeBoundProp(LiveProp $prop): LiveProp
    {
        return $prop->withUrl($this->maybeBoundPropInUrl);
    }

    #[LiveProp(url: new UrlMapping(as: 'q'))]
    public ?string $boundPropWithAlias = null;

    #[LiveProp(url: true, modifier: 'modifyBoundPropWithCustomAlias')]
    public ?string $boundPropWithCustomAlias = null;

    #[LiveProp]
    public ?string $customAlias = null;

    #[LiveProp(writable: true, url: new UrlMapping(mapPath: true))]
    public ?string $pathProp = null;

    #[LiveProp(writable: true, url: new UrlMapping(as: 'pathAlias', mapPath: true))]
    public ?string $pathPropWithAlias = null;

    #[LiveProp(writable: true, url: new UrlMapping(mapPath: true))]
    public ?string $pathPropForAnotherController = 'foo';

    public function modifyBoundPropWithCustomAlias(LiveProp $liveProp): LiveProp
    {
        if ($this->customAlias) {
            $liveProp = $liveProp->withUrl(new UrlMapping(as: $this->customAlias));
        }

        return $liveProp;
    }

    #[LiveAction]
    public function updateLiveProp(#[LiveArg] string $propName, #[LiveArg] mixed $propValue): void
    {
        if (!property_exists($this, $propName)) {
            throw new \InvalidArgumentException(\sprintf('Property "%s" does not exist on component "%s".', $propName, static::class));
        }

        $this->{$propName} = $propValue;
    }

    public function getArrayFieldName(): string
    {
        return 'arr_field_name';
    }
}
